/*
* $Id$
* Copyright (c) 2008-2010 Insprise Software (Shanghai) Co. Ltd.
* All Rights Reserved
* Changelog:
*   Li Guoliang - Jan 16, 2010: Initial version
*/

package com.bizfx.component.controls
{
import flash.events.Event;

import com.bizfx.collections.HashMap;
import com.bizfx.utils.ListUtils;
import com.bizfx.utils.StringUtils;

import mx.collections.ArrayCollection;
import mx.collections.IList;
import mx.controls.CheckBox;
import mx.controls.Tree;
import mx.controls.treeClasses.ITreeDataDescriptor;
import mx.core.ClassFactory;
import mx.logging.ILogger;
import mx.logging.Log;


/**
 * 带有CheckBox的Tree
 */
public class CheckBoxTree extends Tree
{
	protected static const log:ILogger = Log.getLogger("TreeCheckable");

	/** 当前CheckBox被选定的Items. */
	protected var _checkedItems:ArrayCollection;

	protected var _mapofCheckedItems:HashMap;
	
	protected var _mapofItems:HashMap;
	
	private var _checkBoxs:ArrayCollection = new ArrayCollection();
	
	public function addCheckBox(checkBox:CheckBox):void {
		_checkBoxs.addItem(checkBox);
	}

	// Constructor
	public function CheckBoxTree() {
		super();
		_checkedItems = new ArrayCollection();
		_mapofCheckedItems = new HashMap();
		_mapofItems = new HashMap();
		this.itemRenderer = new ClassFactory(CheckBoxTreeItemRenderer);
	}

	/** 设定选定的项目 - 用于设置初始选定项目. */
	public function get checkedItems():ArrayCollection {
		return _checkedItems;
	}

	/** 获得选定的项目, 用于获得选定项目. */
	public function set checkedItems(selectedItems:ArrayCollection):void {
		if (selectedItems != null) {
			for each(var item:Object in selectedItems) {
				addCheckedItem(item);
				this.expandChildrenOf(item, true); // 视图选中, 但不成功, debug进入该方法以查看详情.
				checkChild(item);
				// checkParent(item); // TODO 试图的选中父项目及子项目, 但此时还找不到上级项目...
			}
			invalidateList();	
		}
	}
	
	private var _valueField:String;
	
	public function get valueField():String {
		return this._valueField;
	}

	public function set valueField(value:String):void {
		this._valueField = value;
	}
	
	/** 递归的选定预设选中项目的子项目. */
	protected function checkChild(item:Object):void {
		var dd:ITreeDataDescriptor = dataDescriptor;

		for each(var child:Object in dd.getChildren(item)) {
			addCheckedItem(child);
			checkChild(child);
		}
	}

	/** 统一处理方法: 增加选中的项目. */
	public function addCheckedItem(item:Object):void {
		var key:String = item.toString();
		var i:Object = item;
		if (!StringUtils.isNullOrEmpty(this.valueField) 
			&& item.hasOwnProperty(this.valueField)) {
			key = item[this.valueField].toString();
			for each (var d:Object in this._mapofItems.values()) {
				if (item[this.valueField].toString() == d[this.valueField].toString()) {
					i = d;
					break;
				}
			}
		}
		
		if (!_mapofCheckedItems.containsKey(key)) {
			_mapofCheckedItems.put(key, i);
			_checkedItems.addItem(i);
		}
	}

	/** 统一处理方法: 从已选中项目中移除指定的项目. */
	public function removeCheckedItem(item:Object):void {
		var key:String = item.toString();
		
		if (!StringUtils.isNullOrEmpty(this.valueField) 
			&& item.hasOwnProperty(this.valueField)) {
			key = item[this.valueField].toString();
		}
		
		if (_mapofCheckedItems.containsKey(key)) {
			var i:Object = _mapofCheckedItems.get(key);
			_mapofCheckedItems.remove(key);
			ListUtils.removeFromList(_checkedItems, i);
		}
	}
	
	/** 获得下级项目选定的信息, 如: 3/15 - 15个子项目中选中了3个. 注意: 不含Category. */
	public function getChildCheckedInfo(item:Object):String {
		if(!dataDescriptor.isBranch(item)) {
			log.warn("试图计算叶子的下级选定情况, 返回空字符串.");
			return "";
		}

		var leavesAC:ArrayCollection = new ArrayCollection();
		getAllLeaves(item, leavesAC);

		var checedItemNo:int = 0;
		for each(var leaf:Object in leavesAC) {
			if (!StringUtils.isNullOrEmpty(this.valueField) 
				&& item.hasOwnProperty(this.valueField)) {
				if (_mapofCheckedItems.containsKey(item[this.valueField])) {
					checedItemNo ++;
				}
			} else {
				if (_mapofCheckedItems.containsKey(item.toString())) {
					checedItemNo ++;
				}
			}
		}
		return " (" + checedItemNo + "/" + leavesAC.length + ")";
	}

	/** 递归的将给定项目的所有叶子加入到指定ArrayCollection中. */
	protected function getAllLeaves(item_:Object, leavesAC:ArrayCollection):void {
		for each(var chilid:Object in dataDescriptor.getChildren(item_)) {
			if(dataDescriptor.isBranch(chilid)) {
				getAllLeaves(chilid, leavesAC);
			}else {
				leavesAC.addItem(chilid);
			}
		}
	}


	//--------------------------- 暂未使用方法 ------------------------------------
	/** 递归的选中预设项目的上级项目, 注意: 暂未使用! */
	protected function checkParent(item:Object):void {
		var parent:Object = getParentItem(item);
		if(parent == null) {
			return;
		}
		// log.info("找到上级项目: " + parent + ", 并选定");
		if(!ListUtils.isContains(item, checkedItems)) {
			checkedItems.addItem(item);
		}
		checkParent(parent);
	}

	override public function set dataProvider(value:Object):void {
		if (value !== super.dataProvider) {
			super.dataProvider = value;
			this._mapofCheckedItems.clear();
			this._checkedItems.removeAll();
			this.processItems();
			this.openAllItems();	
		}
	}
	
	private var _enabled:Boolean = true;

	override public function get enabled():Boolean {
		return this._enabled;
	}
	
	override public function set enabled(value:Boolean):void {
		if (_enabled != value) {
			_enabled = value;
			this.dispatchEvent(new Event("checkBoxTreeEnabledChange", true));	
		}
	}

	private function processItem(item:Object):void {
		if (item) {
			var key:String = item.toString();
			if (!StringUtils.isNullOrEmpty(this.valueField) 
				&& item.hasOwnProperty(this.valueField)) {
				key = item[this.valueField].toString();
			}
			this._mapofItems.put(key, item);
			if (item.hasOwnProperty("children")) {				
				if(item.children.length <= 0) {
					delete item.children;
				} else {
					if (item.children is IList) {
						for each(var child:Object in item.children) {
							this.processItem(child);
						}
					}
				}
			}	
		}
	}
	
	public function processItems():void {
		if (this.dataProvider == null) {
			return;
		}
		this._mapofItems = new HashMap();
		if (this.dataProvider is IList) {
			for each(var item:Object in this.dataProvider) {
				if (item) {
					this.processItem(item);
				}
			}
		}
	}
	
	private function openItem(item:Object, openItems:Array):void {
		if (item != null && item.hasOwnProperty("children")) {
			if(item.children.length > 0) {
				openItems.push(item);
				
				if (item.children is IList) {
					for each(var child:Object in item.children) {
						this.openItem(child, openItems);
					}
				} else if (item.children is Array) {
					for (var i:int; i < item.children.length; i++) {
						this.openItem(item.children[i], openItems);
					}	
				}
			}
		}
	}
	
	public function openAllItems():void {
		if (this.dataProvider == null) {
			return;
		}
		var openItems:Array = new Array();
		if (this.dataProvider is IList) {
			for each(var item:Object in this._mapofItems.values()) {
				if (item) {
					openItems.push(item);
				}
			}
		}
		this.openItems = openItems;
	}
} // end class
} // end package